import struct
import logging
import re
import time
from threading import Thread

from utils.channels.webSocketTransfer import WebSocketTransfer
from utils.socket.udp import Udp
from utils.string.hex_utils import bytes_to_hex_str
from utils.string.hex_utils import hex_str_to_bytes

logger = logging.getLogger()


class CommandSendChannel(Udp):
    def __init__(self):
        super().__init__('127.0.0.1', 23000, local_port=23001)

    def send_cmd(self, data):
        """
        若data为str类型：将data解析成bytes再进行发送，如： 'AABBCC' 解析成 b'AABBCC'
        若data为bytes类型：则直接进行数据发送
        """
        if isinstance(data, str):
            send_data = hex_str_to_bytes(data)
        else:
            send_data = data
        self.send(send_data)


class CommandReceiveChannel(Udp):
    def __init__(self):
        super().__init__('127.0.0.1', 22001, local_port=22000)


class StatusChannel(Udp):
    def __init__(self):
        super().__init__('127.0.0.1', 21001, local_port=21000)


class StationStateReceiveChannel(Udp):
    def __init__(self):
        super().__init__('127.0.0.1', 20001, local_port=20000)


class LowerComputer:
    TIME_OUT = 15

    def __init__(self):
        # self.__status_channel_que = Queue()
        self.__wait_response_list = []
        self.__cmd_send_channel = CommandSendChannel()

        self.__cmd_recv_channel = CommandReceiveChannel()
        self.__cmd_recv_channel_thread = Thread(target=self.__cmd_recv_channel_worker).start()

        self.__status_channel = StatusChannel()
        self.__status_channel_thread = Thread(target=self.__status_channel_worker).start()

        self.__station_state_recv_channel = StationStateReceiveChannel()
        self.__station_state_recv_thread = Thread(target=self.__station_state_recv_worker).start()

    def send_bytes(self, bytes_data):
        self.__cmd_send_channel.send_cmd(bytes_data)

    def send_cmd_event(self, content):
        send_data = content['data'].lower()
        send_data = re.sub(r'[^0-9a-f]*', '', send_data, flags=re.IGNORECASE)
        if send_data not in self.__wait_response_list:
            self.__wait_response_list.append(send_data)
        self.__cmd_send_channel.send_cmd(send_data)
        s_time = time.time()
        while True:
            e_time = time.time()
            if (e_time - s_time) > self.TIME_OUT:
                logger.warning('指令[%s]响应超时' % send_data)
                del self.__wait_response_list[self.__wait_response_list.index(send_data)]
                return None
            if not (send_data in self.__wait_response_list):
                return 'ok'

    def __cmd_recv_channel_worker(self):
        while True:
            bytes_data, source_addr = self.__cmd_recv_channel.recv()
            recv_data = bytes_to_hex_str(bytes_data).lower()
            if recv_data in self.__wait_response_list:
                del self.__wait_response_list[self.__wait_response_list.index(recv_data)]

    def __status_channel_worker(self):
        while True:
            bytes_data, source_addr = self.__status_channel.recv()
            recv_data = bytes_to_hex_str(bytes_data).lower()
            WebSocketTransfer.push_data_send(recv_data, 'status')

    def __station_state_recv_worker(self):
        while True:
            push_data = {}
            bytes_data, source_addr = self.__station_state_recv_channel.recv()

            # cpu温度解析
            cpu_temp = '%.2f' % (float(bytes_data[9:9+bytes_data[8]])/1000)
            # UTC时间解析
            (utc_s, cTime_us) = struct.unpack('>QQ', bytes_data[19:35])
            utc_ms = utc_s*1000+cTime_us/1000
            # 存储空间解析
            (disk_used, disk_remain) = struct.unpack('>II', bytes_data[35:43])

            push_data['cpuTemp'] = cpu_temp
            push_data['utcMilliseconds'] = utc_ms
            push_data['diskUsed'] = disk_used
            push_data['diskRemain'] = disk_remain
            push_data['separateState'] = True if bytes_data[6] == int(0x55) else False
            push_data['recoveryState'] = True if bytes_data[7] == int(0x55) else False
            push_data['KCHSDWZFState'] = True if bytes_data[43] == int(0x55) else False  # 开出回收到位转发信号
            WebSocketTransfer.push_data_send(push_data, 'station_status', data_type='json')


try:
    lower_computer = LowerComputer()
    logger.info("下位机通讯已就绪")
except Exception as e:
    logger.error("下位机通讯建立异常:", str(e))
